<!DOCTYPE HTML>
<head>
<meta charset="UTF-8">
<style>
@font-face {
  font-family: Libertine;
  src: url('../../third_party/Libertine/LinLibertine_R.woff');
}
</style>
</head>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>

const kAligns = [ "left", "right", "center", "start", "end" ];

const kTexts = [
  { text: "Hello", rtl: false },
  { text: "傳統是假的", rtl: false },
  { text: "フェミニズム", rtl: false },
  { text: "ليس", rtl: true },
  { text: "ليس في اسمنا", rtl: true },
  { text: "\u202EHello", rtl: true },
  { text: "\u202EHello World", rtl: true },
  { text: "الله", rtl: true }, // Special ligatures.
  { text: "اين المكتبة؟", rtl: true }, // Special ligatures.
  { text: "🏁🎶🏁", rtl: false }, // One glyph with two "characters".
  { text: "एक आम भाषा", rtl: false }, // Special post-modifying characters.
  { text: "a\u0301", rtl: false }, // Combining diacritical marks
]

function forEachExample(fn) {
  for (const ex of kTexts) {
    for (const align of kAligns) {
      fn(ex, align);
    }
  }
}

function isNonIncreasing(array) {
  for (var i = 1; i < array.length; i++) {
    if (array[i] > array[i-1]) {
      return false;
    }
  }
  return true;
}

function isNonDecreasing(array) {
  for (var i = 1; i < array.length; i++) {
    if (array[i] < array[i-1]) {
      return false;
    }
  }
  return true;
}

function getTextMetrics(ctx, text, align="left", direction="ltr") {
  ctx.font = '25px Libertine';
  ctx.textAlign = align;
  ctx.direction = direction;
  return ctx.measureText(text);
}

function testEmptyStringReturnsEmptyAdvances(ctx) {
  const tm = getTextMetrics(ctx, "");
  assert_array_equals(tm.advances, [], "Empty string must return empty advances");
}

function testAllPositive(ctx) {
  forEachExample((ex, align) => {
      const tm = getTextMetrics(ctx, ex.text, align, ex.rtl ? "rtl" : "ltr", );
      assert_true(tm.advances.every(function isPositive(i) {return i >= 0; }),
        "Advances must be all positive (" + ex.text + ")");
  });
}

function testNonIncreasingForRtl(ctx) {
  forEachExample((ex, align) => {
      if (ex.rtl) {
        const tm = getTextMetrics(ctx, ex.text, align, ex.rtl ? "rtl" : "ltr");
        assert_true(isNonIncreasing(tm.advances),
         "RTL advances must be non-increasing (" + ex.text + ")");
      }
  });
}

function testNonDecreasingForLtr(ctx) {
  forEachExample((ex, align) => {
      if (! ex.rtl) {
        const tm = getTextMetrics(ctx, ex.text, align, ex.rtl ? "rtl" : "ltr");
        assert_true(isNonDecreasing(tm.advances),
         "LTR advances must be non-decreasing (" + ex.text + ")");
      }
  });
}

function testLastAdvanceLessThanWith(ctx) {
  forEachExample((ex, align) => {
      const tm = getTextMetrics(ctx, ex.text, align, ex.rtl ? "rtl" : "ltr");
      assert_less_than(tm.advances.slice(-1)[0], tm.width,
        "Last advance must be strictly less than total width (" + ex.text + ")");
  });
}

function testAdvances(ctx) {
  testEmptyStringReturnsEmptyAdvances(ctx);
  testAllPositive(ctx);
  testNonIncreasingForRtl(ctx);
  testNonDecreasingForLtr(ctx);
  testLastAdvanceLessThanWith(ctx);
}

async_test(t => {
  var canvas = document.createElement('canvas');
  canvas.width = 100;
  canvas.height = 100;
  var ctx = canvas.getContext('2d');
  // Kick off loading of the font
  ctx.font = '50px Libertine';
  ctx.fillText(" ", 0, 0);
  document.fonts.ready.then(t.step_func_done(testAdvances(ctx)));
}, "Test TextMetrics advances.");
</script>
